package routers

import (
	"gitee.com/aldrice/monitor/api"
	. "gitee.com/aldrice/monitor/configs"
	router2 "gitee.com/aldrice/monitor/internal/router"
	. "gitee.com/aldrice/monitor/pkg/logging"
	"github.com/go-playground/validator/v10"
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
	"go.uber.org/zap"
	"io"
	"net/http"
	"net/http/pprof"
	"os"
	"path/filepath"
)

type customValidator struct {
	engine *validator.Validate
}

func (v *customValidator) Validate(i interface{}) error {
	err := v.engine.Struct(i)
	if err == nil {
		return nil
	}
	return router2.ApiException(400, 10004, err.Error())
}

// ApiRouter Create New Router For All APIs
func ApiRouter() *echo.Echo {
	r := echo.New()
	r.Use(router2.WrapContext)
	r.HTTPErrorHandler = router2.HttpErrorHandler

	r.HideBanner = true
	r.HidePort = true

	var logWriter io.Writer
	accessFile := filepath.Join(Config.Path.Log, "access.log")
	logWriter, err := os.OpenFile(accessFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		Logger().Fatal("init access log file failed", zap.Error(err))
	}

	if Config.IsProd {
		r.Use(middleware.Recover())
	} else {
		cfg := middleware.DefaultCORSConfig
		cfg.MaxAge = 86400
		r.Use(middleware.CORSWithConfig(cfg))
		r.Debug = true
		logWriter = io.MultiWriter(logWriter, os.Stdout)
		RoutePProf(r.Group("/debug/pprof"))
	}

	r.Use(middleware.Secure())
	r.Validator = &customValidator{engine: validator.New()}

	// todo: RateLimit

	api.RoutesAuth(r.Group("/auth"))
	api.RoutesUser(r.Group("/user"))
	api.RoutesMonitor(r.Group("/monitor"))
	return r
}

func RoutePProf(router *echo.Group) {
	router.GET("/", echo.WrapHandler(http.HandlerFunc(pprof.Index)))
	router.GET("/allocs", echo.WrapHandler(http.HandlerFunc(pprof.Index)))
	router.GET("/block", echo.WrapHandler(http.HandlerFunc(pprof.Index)))
	router.GET("/goroutine", echo.WrapHandler(http.HandlerFunc(pprof.Index)))
	router.GET("/heap", echo.WrapHandler(http.HandlerFunc(pprof.Index)))
	router.GET("/mutex", echo.WrapHandler(http.HandlerFunc(pprof.Index)))
	router.GET("/cmdline", echo.WrapHandler(http.HandlerFunc(pprof.Cmdline)))
	router.GET("/profile", echo.WrapHandler(http.HandlerFunc(pprof.Profile)))
	router.GET("/symbol", echo.WrapHandler(http.HandlerFunc(pprof.Symbol)))
	router.GET("/trace", echo.WrapHandler(http.HandlerFunc(pprof.Trace)))
}
